<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PlantUML 架构图交互演示</title>
    <script src="https://unpkg.com/plantuml-encoder@1.4.0/dist/plantuml-encoder.min.js"></script>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
        
        .demo-header {
            text-align: center;
            margin-bottom: 30px;
            color: white;
        }
        
        .demo-header h1 {
            margin: 0;
            font-size: 2.5em;
            text-shadow: 0 2px 10px rgba(0,0,0,0.3);
        }
        
        .demo-container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            border-radius: 16px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
            overflow: hidden;
        }
        
        .control-panel {
            background: linear-gradient(90deg, #2c3e50 0%, #34495e 100%);
            color: white;
            padding: 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
        }
        
        .control-group {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .control-panel button {
            background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
            color: white;
            border: none;
            padding: 10px 18px;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.3s ease;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        
        .control-panel button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
        }
        
        .status-indicator {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 14px;
        }
        
        .status-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #27ae60;
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }
        
        .plantuml-container {
            position: relative;
            padding: 40px;
            min-height: 600px;
            display: flex;
            justify-content: center;
            align-items: center;
            background: #f8f9fa;
        }
        
        .node-overlay {
            position: absolute;
            pointer-events: none;
            z-index: 10;
        }
        
        .node-badge {
            position: absolute;
            color: white;
            border-radius: 12px;
            padding: 4px 8px;
            font-size: 11px;
            font-weight: bold;
            z-index: 15;
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
            transition: all 0.3s ease;
        }
        
        .badge-healthy { background: linear-gradient(135deg, #27ae60, #2ecc71); }
        .badge-warning { background: linear-gradient(135deg, #f39c12, #e67e22); }
        .badge-critical { background: linear-gradient(135deg, #e74c3c, #c0392b); }
        .badge-maintenance { background: linear-gradient(135deg, #9b59b6, #8e44ad); }
        
        .node-pulse {
            position: absolute;
            border: 3px solid #27ae60;
            border-radius: 50%;
            animation: pulseRing 2s infinite;
            z-index: 12;
        }
        
        @keyframes pulseRing {
            0% { transform: scale(1); opacity: 1; }
            50% { transform: scale(1.3); opacity: 0.7; }
            100% { transform: scale(1); opacity: 1; }
        }
        
        .click-indicator {
            position: absolute;
            width: 30px;
            height: 30px;
            border: 4px solid #3498db;
            border-radius: 50%;
            pointer-events: none;
            z-index: 20;
            animation: clickRipple 0.8s ease-out;
        }
        
        @keyframes clickRipple {
            0% { 
                transform: scale(0); 
                opacity: 1; 
                border-width: 4px;
            }
            100% { 
                transform: scale(2.5); 
                opacity: 0; 
                border-width: 1px;
            }
        }
        
        .node-info-panel {
            position: absolute;
            background: white;
            border: 3px solid #3498db;
            border-radius: 16px;
            padding: 25px;
            box-shadow: 0 15px 35px rgba(0,0,0,0.2);
            z-index: 25;
            display: none;
            min-width: 320px;
            max-width: 450px;
            backdrop-filter: blur(10px);
        }
        
        .panel-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #ecf0f1;
        }
        
        .panel-title {
            font-size: 18px;
            font-weight: bold;
            color: #2c3e50;
            margin: 0;
        }
        
        .panel-status {
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: bold;
            color: white;
        }
        
        .metrics-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 12px;
            margin-bottom: 20px;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 12px;
        }
        
        .metric-item {
            text-align: center;
            padding: 10px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
        }
        
        .metric-value {
            font-size: 20px;
            font-weight: bold;
            color: #3498db;
            display: block;
        }
        
        .metric-label {
            font-size: 12px;
            color: #7f8c8d;
            margin-top: 4px;
        }
        
        .actions-section {
            margin-bottom: 20px;
        }
        
        .section-title {
            font-size: 14px;
            font-weight: bold;
            color: #2c3e50;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .action-button {
            display: flex;
            align-items: center;
            justify-content: space-between;
            width: 100%;
            padding: 12px 16px;
            margin: 8px 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 10px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s ease;
            box-shadow: 0 3px 10px rgba(0,0,0,0.1);
        }
        
        .action-button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(0,0,0,0.2);
        }
        
        .action-button:active {
            transform: translateY(0);
        }
        
        .action-info {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .action-timeout {
            font-size: 11px;
            opacity: 0.8;
            background: rgba(255,255,255,0.2);
            padding: 2px 8px;
            border-radius: 12px;
        }
        
        .panel-footer {
            display: flex;
            justify-content: space-between;
            gap: 12px;
        }
        
        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
            flex: 1;
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #3498db, #2980b9);
            color: white;
        }
        
        .btn-secondary {
            background: #95a5a6;
            color: white;
        }
        
        .btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.2);
        }
        
        .loading-overlay {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(255,255,255,0.9);
            display: none;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 1500;
            backdrop-filter: blur(5px);
        }
        
        .spinner {
            width: 50px;
            height: 50px;
            border: 5px solid #f3f3f3;
            border-top: 5px solid #3498db;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin-bottom: 20px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .loading-text {
            color: #2c3e50;
            font-size: 16px;
            font-weight: 500;
        }
        
        .execution-modal {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0,0,0,0.6);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 3000;
            backdrop-filter: blur(5px);
        }
        
        .modal-content {
            background: white;
            border-radius: 16px;
            padding: 30px;
            max-width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            animation: modalSlideIn 0.3s ease-out;
        }
        
        @keyframes modalSlideIn {
            from {
                opacity: 0;
                transform: translateY(-50px) scale(0.9);
            }
            to {
                opacity: 1;
                transform: translateY(0) scale(1);
            }
        }
        
        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #ecf0f1;
        }
        
        .modal-title {
            font-size: 20px;
            font-weight: bold;
            color: #2c3e50;
            margin: 0;
        }
        
        .close-btn {
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            color: #7f8c8d;
            padding: 5px;
            border-radius: 50%;
            width: 35px;
            height: 35px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .close-btn:hover {
            background: #ecf0f1;
            color: #2c3e50;
        }
        
        .execution-info {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 10px;
            margin-bottom: 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 10px;
        }
        
        .execution-output {
            background: #2c3e50;
            color: #ecf0f1;
            padding: 20px;
            border-radius: 10px;
            font-family: 'Courier New', monospace;
            font-size: 13px;
            line-height: 1.5;
            white-space: pre-wrap;
            max-height: 300px;
            overflow-y: auto;
            border: 2px solid #34495e;
        }
        
        .warning-indicator {
            animation: warningBlink 1s infinite;
        }
        
        @keyframes warningBlink {
            0%, 50% { opacity: 1; }
            51%, 100% { opacity: 0.6; }
        }
        
        .node-enhanced {
            cursor: pointer !important;
            transition: all 0.3s ease;
        }
        
        .node-highlighted {
            filter: drop-shadow(0 0 12px #3498db) brightness(1.1);
            transform: scale(1.02);
        }
        
        @media (max-width: 768px) {
            .demo-container {
                margin: 10px;
                border-radius: 12px;
            }
            
            .control-panel {
                flex-direction: column;
                gap: 15px;
                text-align: center;
            }
            
            .node-info-panel {
                max-width: 90vw;
                left: 5vw !important;
                right: 5vw !important;
            }
            
            .metrics-grid {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="demo-header">
        <h1>🎨 PlantUML 架构图交互演示</h1>
        <p>体验基于坐标检测的精确节点交互</p>
    </div>
    
    <div class="demo-container">
        <div class="control-panel">
            <div class="control-group">
                <div class="status-indicator">
                    <div class="status-dot"></div>
                    <span>架构图在线</span>
                </div>
                <span id="diagram-info">PlantUML v8059</span>
            </div>
            
            <div class="control-group">
                <button onclick="reloadDiagram()">🔄 重新加载</button>
                <button onclick="analyzeDiagram()">🔍 结构分析</button>
                <button onclick="exportSVG()">📥 导出SVG</button>
                <button onclick="toggleDevMode()">⚙️ 开发模式</button>
            </div>
        </div>
        
        <div id="plantuml-container" class="plantuml-container">
            <div class="loading-overlay" id="loading-overlay">
                <div class="spinner"></div>
                <div class="loading-text">正在生成架构图...</div>
            </div>
        </div>
    </div>
    
    <!-- 节点信息面板 -->
    <div id="node-info-panel" class="node-info-panel">
        <div class="panel-header">
            <h4 class="panel-title" id="panel-title">节点详情</h4>
            <div class="panel-status" id="panel-status">运行中</div>
        </div>
        
        <div id="panel-metrics" class="metrics-grid"></div>
        
        <div class="actions-section">
            <div class="section-title">
                ⚡ 可用操作
            </div>
            <div id="action-list"></div>
        </div>
        
        <div class="panel-footer">
            <button class="btn btn-primary" onclick="refreshNodeMetrics()">🔄 刷新</button>
            <button class="btn btn-secondary" onclick="hideInfoPanel()">✖️ 关闭</button>
        </div>
    </div>
    
    <!-- 执行结果模态框 -->
    <div id="execution-modal" class="execution-modal" onclick="hideExecutionModal(event)">
        <div class="modal-content" onclick="event.stopPropagation()">
            <div class="modal-header">
                <h4 class="modal-title" id="modal-title">执行结果</h4>
                <button class="close-btn" onclick="hideExecutionModal()">&times;</button>
            </div>
            
            <div id="execution-info" class="execution-info"></div>
            <div id="execution-output" class="execution-output"></div>
            
            <div style="margin-top: 20px; text-align: right;">
                <button class="btn btn-primary" onclick="copyOutput()">📋 复制输出</button>
                <button class="btn btn-secondary" onclick="hideExecutionModal()">关闭</button>
            </div>
        </div>
    </div>

    <script>
        const plantUmlCode = `
            @startuml architecture
            !theme blueprint
            
            skinparam node {
                BackgroundColor #f8f9fa
                BorderColor #2c3e50
                BorderThickness 2
                FontSize 12
                FontColor #2c3e50
            }
            
            skinparam arrow {
                Color #3498db
                Thickness 2
            }
            
            node "🌐 API Gateway\\n网关服务" as api #lightblue {
                [路由] as route
                [负载均衡] as lb
            }
            
            node "👥 User Service\\n用户管理" as user #lightgreen {
                [认证] as auth
                [用户数据] as userdata
            }
            
            node "📦 Order Service\\n订单处理" as order #lightyellow {
                [订单逻辑] as orderlogic
                [库存管理] as inventory
            }
            
            node "💳 Payment Service\\n支付处理" as payment #lightcyan {
                [支付网关] as paygate
                [风控] as risk
            }
            
            node "📊 Analytics Service\\n数据分析" as analytics #lightpink {
                [报表] as report
                [统计] as stats
            }
            
            database "🗄️ Primary DB\\n主数据库" as db #lightgray
            database "⚡ Redis Cache\\n缓存层" as cache #orange
            cloud "🌍 External APIs\\n外部服务" as external #lightsteelblue
            
            api --> user : "用户请求"
            api --> order : "订单请求"
            api --> payment : "支付请求"
            api --> analytics : "数据请求"
            
            user --> db : "用户数据"
            order --> db : "订单数据"
            payment --> db : "支付数据"
            analytics --> db : "查询数据"
            
            user --> cache : "会话缓存"
            order --> cache : "订单缓存"
            payment --> cache : "临时数据"
            
            payment --> external : "第三方支付"
            analytics --> external : "数据源"
            
            note right of api : 高可用架构\\n支持水平扩展
            note bottom of db : 主从复制\\n定期备份
            
            @enduml
        `;
        
        // 节点配置信息
        const nodeConfigurations = {
            'API Gateway': {
                id: 'api',
                type: 'gateway',
                status: 'healthy',
                description: '系统入口网关，负责请求路由和负载均衡',
                metrics: {
                    'CPU': '23%',
                    '内存': '512MB',
                    'QPS': '1.2K',
                    '延迟': '15ms'
                },
                actions: [
                    { id: 'health_check', name: '健康检查', icon: '❤️', timeout: 30 },
                    { id: 'view_logs', name: '查看日志', icon: '📋', timeout: 15 },
                    { id: 'performance', name: '性能监控', icon: '📊', timeout: 20 },
                    { id: 'restart', name: '重启服务', icon: '🔄', timeout: 60 }
                ]
            },
            'User Service': {
                id: 'user',
                type: 'service',
                status: 'warning',
                description: '用户管理服务，处理认证和用户数据管理',
                metrics: {
                    'CPU': '67%',
                    '内存': '1.1GB',
                    '连接数': '456',
                    '用户数': '15.6K'
                },
                actions: [
                    { id: 'user_count', name: '用户统计', icon: '👥', timeout: 20 },
                    { id: 'auth_check', name: '认证检查', icon: '🔐', timeout: 15 },
                    { id: 'cleanup_sessions', name: '清理会话', icon: '🧹', timeout: 45 },
                    { id: 'user_report', name: '用户报告', icon: '📈', timeout: 30 }
                ]
            },
            'Order Service': {
                id: 'order',
                type: 'service', 
                status: 'healthy',
                description: '订单处理服务，管理订单生命周期和库存',
                metrics: {
                    'CPU': '34%',
                    '内存': '896MB',
                    '订单/时': '156',
                    '库存量': '2.3K'
                },
                actions: [
                    { id: 'order_count', name: '订单统计', icon: '📊', timeout: 20 },
                    { id: 'inventory_check', name: '库存检查', icon: '📦', timeout: 25 },
                    { id: 'order_sync', name: '订单同步', icon: '🔄', timeout: 45 },
                    { id: 'stock_alert', name: '库存预警', icon: '⚠️', timeout: 15 }
                ]
            },
            'Payment Service': {
                id: 'payment',
                type: 'service',
                status: 'healthy',
                description: '支付处理服务，集成多种支付方式和风控',
                metrics: {
                    'CPU': '12%',
                    '内存': '445MB',
                    '成功率': '98.5%',
                    '日交易': '¥234K'
                },
                actions: [
                    { id: 'payment_status', name: '支付状态', icon: '💰', timeout: 15 },
                    { id: 'fraud_check', name: '风控检查', icon: '🛡️', timeout: 20 },
                    { id: 'payment_report', name: '交易报告', icon: '📊', timeout: 25 },
                    { id: 'reconcile', name: '对账处理', icon: '🔍', timeout: 120 }
                ]
            },
            'Analytics Service': {
                id: 'analytics',
                type: 'service',
                status: 'maintenance',
                description: '数据分析服务，提供业务洞察和报表',
                metrics: {
                    'CPU': '45%',
                    '内存': '2.1GB',
                    '任务数': '23',
                    '报表': '156'
                },
                actions: [
                    { id: 'generate_report', name: '生成报表', icon: '📊', timeout: 60 },
                    { id: 'data_sync', name: '数据同步', icon: '🔄', timeout: 90 },
                    { id: 'analytics_health', name: '健康检查', icon: '❤️', timeout: 30 },
                    { id: 'clear_cache', name: '清理缓存', icon: '🧹', timeout: 20 }
                ]
            },
            'Primary DB': {
                id: 'db',
                type: 'database',
                status: 'critical',
                description: '主数据库，存储所有核心业务数据',
                metrics: {
                    'CPU': '89%',
                    '内存': '3.2GB',
                    '连接': '78/100',
                    'QPS': '1.5K'
                },
                actions: [
                    { id: 'db_status', name: '数据库状态', icon: '🔍', timeout: 10 },
                    { id: 'performance_check', name: '性能检查', icon: '⚡', timeout: 30 },
                    { id: 'backup_data', name: '数据备份', icon: '💾', timeout: 300 },
                    { id: 'optimize_queries', name: '查询优化', icon: '🚀', timeout: 60 }
                ]
            },
            'Redis Cache': {
                id: 'cache',
                type: 'cache',
                status: 'healthy',
                description: 'Redis缓存服务，提升系统响应速度',
                metrics: {
                    'CPU': '8%',
                    '内存': '1.2GB',
                    '命中率': '96.8%',
                    '键数': '157K'
                },
                actions: [
                    { id: 'cache_status', name: '缓存状态', icon: '⚡', timeout: 5 },
                    { id: 'cache_stats', name: '统计信息', icon: '📊', timeout: 10 },
                    { id: 'clear_cache', name: '清理缓存', icon: '🧹', timeout: 15 },
                    { id: 'cache_backup', name: '缓存备份', icon: '💾', timeout: 45 }
                ]
            },
            'External APIs': {
                id: 'external',
                type: 'external',
                status: 'healthy',
                description: '外部API服务，第三方系统集成',
                metrics: {
                    '可用性': '99.2%',
                    '响应时间': '245ms',
                    '调用量': '567',
                    '错误率': '0.8%'
                },
                actions: [
                    { id: 'api_health', name: '接口检查', icon: '🌐', timeout: 20 },
                    { id: 'api_stats', name: '调用统计', icon: '📈', timeout: 15 },
                    { id: 'api_test', name: '接口测试', icon: '🧪', timeout: 30 },
                    { id: 'api_monitor', name: '监控配置', icon: '👁️', timeout: 25 }
                ]
            }
        };
        
        let nodeAreas = [];
        let overlayElements = [];
        let currentSelectedNode = null;
        let devMode = false;
        let lastExecutionResult = null;
        
        // 初始化PlantUML图表
        async function initializePlantUMLDiagram() {
            showLoading(true, '正在生成架构图...');
            
            try {
                const encoded = plantumlEncoder.encode(plantUmlCode);
                const svgUrl = `https://www.plantuml.com/plantuml/svg/${encoded}`;
                
                const response = await fetch(svgUrl);
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }
                
                const svgText = await response.text();
                
                const parser = new DOMParser();
                const svgDoc = parser.parseFromString(svgText, "image/svg+xml");
                const svgElement = svgDoc.documentElement;
                
                // 设置SVG样式
                svgElement.style.maxWidth = '100%';
                svgElement.style.height = 'auto';
                svgElement.style.filter = 'drop-shadow(0 4px 20px rgba(0,0,0,0.1))';
                
                // 插入SVG到容器
                const container = document.getElementById('plantuml-container');
                const existingSvg = container.querySelector('svg');
                if (existingSvg) {
                    container.removeChild(existingSvg);
                }
                container.appendChild(svgElement);
                
                // 分析并增强SVG
                setTimeout(() => {
                    analyzeSVGStructure(svgElement, container);
                    updateDiagramInfo();
                    showLoading(false);
                }, 500);
                
            } catch (error) {
                console.error('PlantUML图表加载失败:', error);
                showLoading(false);
                showNotification('图表加载失败: ' + error.message, 'error');
            }
        }
        
        // 分析SVG结构并建立节点映射
        function analyzeSVGStructure(svgElement, container) {
            nodeAreas = [];
            
            // 清除旧的叠加元素
            overlayElements.forEach(el => {
                if (el.parentNode) {
                    el.parentNode.removeChild(el);
                }
            });
            overlayElements = [];
            
            // 查找所有文本元素
            const textElements = svgElement.querySelectorAll('text');
            
            textElements.forEach(textEl => {
                const textContent = textEl.textContent.trim();
                
                // 匹配节点名称
                const nodeConfig = findNodeConfigByText(textContent);
                
                if (nodeConfig) {
                    // 查找关联的图形元素
                    const graphicElement = findAssociatedGraphic(textEl);
                    
                    if (graphicElement) {
                        const bbox = graphicElement.getBBox();
                        
                        // 计算绝对坐标
                        const ctm = graphicElement.getCTM();
                        const actualBounds = {
                            x: bbox.x + (ctm ? ctm.e : 0),
                            y: bbox.y + (ctm ? ctm.f : 0),
                            width: bbox.width,
                            height: bbox.height
                        };
                        
                        const nodeArea = {
                            nodeId: nodeConfig.id,
                            nodeName: textContent,
                            config: nodeConfig,
                            element: graphicElement,
                            textElement: textEl,
                            bounds: actualBounds
                        };
                        
                        nodeAreas.push(nodeArea);
                        
                        // 添加增强元素
                        addNodeEnhancements(container, nodeArea);
                        
                        if (devMode) {
                            addDebugOverlay(container, nodeArea);
                        }
                    }
                }
            });
            
            // 设置点击检测
            setupClickDetection(svgElement, container);
            
            console.log(`发现 ${nodeAreas.length} 个可交互节点`);
        }
        
        // 根据文本内容查找节点配置
        function findNodeConfigByText(text) {
            for (const [key, config] of Object.entries(nodeConfigurations)) {
                if (text.includes(key) || 
                    text.includes(config.id) ||
                    (key.includes('Service') && text.includes('Service')) ||
                    (key.includes('Gateway') && text.includes('Gateway')) ||
                    (key.includes('DB') && text.includes('DB')) ||
                    (key.includes('Cache') && text.includes('Cache')) ||
                    (key.includes('APIs') && text.includes('APIs'))) {
                    return config;
                }
            }
            return null;
        }
        
        // 查找文本关联的图形元素
        function findAssociatedGraphic(textElement) {
            // 方法1: 查找父级group中的图形元素
            let parent = textElement.parentElement;
            while (parent && parent.tagName !== 'svg') {
                const graphic = parent.querySelector('rect, ellipse, polygon, path[d*="M"]');
                if (graphic && graphic !== textElement) {
                    return graphic;
                }
                parent = parent.parentElement;
            }
            
            // 方法2: 查找相邻的图形元素
            const siblings = textElement.parentElement.children;
            for (let sibling of siblings) {
                if (sibling !== textElement && 
                    ['rect', 'ellipse', 'polygon', 'path'].includes(sibling.tagName)) {
                    return sibling;
                }
            }
            
            return null;
        }
        
        // 为节点添加增强元素
        function addNodeEnhancements(container, nodeArea) {
            // 添加状态徽章
            addStatusBadge(container, nodeArea);
            
            // 添加活动指示器
            if (nodeArea.config.status === 'healthy') {
                addActivityIndicator(container, nodeArea);
            }
            
            // 添加警告指示器
            if (nodeArea.config.status === 'warning' || nodeArea.config.status === 'critical') {
                addWarningIndicator(container, nodeArea);
            }
            
            // 添加维护指示器
            if (nodeArea.config.status === 'maintenance') {
                addMaintenanceIndicator(container, nodeArea);
            }
        }
        
        // 添加状态徽章
        function addStatusBadge(container, nodeArea) {
            const badge = document.createElement('div');
            badge.className = `node-badge badge-${nodeArea.config.status}`;
            
            const statusText = {
                'healthy': '正常',
                'warning': '警告',
                'critical': '严重',
                'maintenance': '维护'
            };
            
            badge.textContent = statusText[nodeArea.config.status] || '未知';
            badge.title = `${nodeArea.config.name} - ${badge.textContent}`;
            
            positionElement(badge, nodeArea, 'top-right', -8, -8);
            
            container.appendChild(badge);
            overlayElements.push(badge);
        }
        
        // 添加活动指示器
        function addActivityIndicator(container, nodeArea) {
            const indicator = document.createElement('div');
            indicator.className = 'node-pulse';
            
            positionElement(indicator, nodeArea, 'top-left', -8, -8);
            indicator.style.width = '16px';
            indicator.style.height = '16px';
            
            container.appendChild(indicator);
            overlayElements.push(indicator);
        }
        
        // 添加警告指示器
        function addWarningIndicator(container, nodeArea) {
            const warning = document.createElement('div');
            warning.innerHTML = nodeArea.config.status === 'critical' ? '🚨' : '⚠️';
            warning.className = 'warning-indicator';
            warning.style.position = 'absolute';
            warning.style.fontSize = '20px';
            warning.style.zIndex = '15';
            warning.title = '需要注意';
            
            positionElement(warning, nodeArea, 'bottom-left', -8, 8);
            
            container.appendChild(warning);
            overlayElements.push(warning);
        }
        
        // 添加维护指示器
        function addMaintenanceIndicator(container, nodeArea) {
            const maintenance = document.createElement('div');
            maintenance.innerHTML = '🔧';
            maintenance.style.position = 'absolute';
            maintenance.style.fontSize = '18px';
            maintenance.style.zIndex = '15';
            maintenance.title = '维护中';
            
            positionElement(maintenance, nodeArea, 'bottom-right', 8, 8);
            
            container.appendChild(maintenance);
            overlayElements.push(maintenance);
        }
        
        // 添加调试叠加层
        function addDebugOverlay(container, nodeArea) {
            const overlay = document.createElement('div');
            overlay.style.cssText = `
                position: absolute;
                border: 2px dashed #e74c3c;
                background: rgba(231, 76, 60, 0.1);
                pointer-events: none;
                z-index: 5;
                font-size: 10px;
                color: #e74c3c;
                padding: 2px;
            `;
            overlay.textContent = nodeArea.nodeId;
            
            const bounds = nodeArea.bounds;
            overlay.style.left = bounds.x + 'px';
            overlay.style.top = bounds.y + 'px';
            overlay.style.width = bounds.width + 'px';
            overlay.style.height = bounds.height + 'px';
            
            container.appendChild(overlay);
            overlayElements.push(overlay);
        }
        
        // 元素定位辅助函数
        function positionElement(element, nodeArea, position, offsetX = 0, offsetY = 0) {
            const bounds = nodeArea.bounds;
            element.style.position = 'absolute';
            
            switch (position) {
                case 'top-left':
                    element.style.left = (bounds.x + offsetX) + 'px';
                    element.style.top = (bounds.y + offsetY) + 'px';
                    break;
                case 'top-right':
                    element.style.left = (bounds.x + bounds.width + offsetX) + 'px';
                    element.style.top = (bounds.y + offsetY) + 'px';
                    break;
                case 'bottom-left':
                    element.style.left = (bounds.x + offsetX) + 'px';
                    element.style.top = (bounds.y + bounds.height + offsetY) + 'px';
                    break;
                case 'bottom-right':
                    element.style.left = (bounds.x + bounds.width + offsetX) + 'px';
                    element.style.top = (bounds.y + bounds.height + offsetY) + 'px';
                    break;
                case 'center':
                    element.style.left = (bounds.x + bounds.width/2 + offsetX) + 'px';
                    element.style.top = (bounds.y + bounds.height/2 + offsetY) + 'px';
                    break;
            }
        }
        
        // 设置点击检测
        function setupClickDetection(svgElement, container) {
            svgElement.style.cursor = 'default';
            
            // 添加鼠标悬停效果
            svgElement.addEventListener('mousemove', (event) => {
                const clickedNode = detectNodeAtPosition(event);
                
                if (clickedNode) {
                    svgElement.style.cursor = 'pointer';
                    if (!clickedNode.element.classList.contains('node-enhanced')) {
                        clickedNode.element.classList.add('node-enhanced');
                    }
                } else {
                    svgElement.style.cursor = 'default';
                }
            });
            
            svgElement.addEventListener('click', (event) => {
                const clickedNode = detectNodeAtPosition(event);
                
                if (clickedNode) {
                    handleNodeClick(event, clickedNode, container);
                } else {
                    // 点击空白区域，隐藏面板
                    hideInfoPanel();
                }
            });
        }
        
        // 检测指定位置的节点
        function detectNodeAtPosition(event) {
            const svg = event.currentTarget;
            const rect = svg.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            
            for (let nodeArea of nodeAreas) {
                const bounds = nodeArea.bounds;
                
                if (x >= bounds.x && x <= bounds.x + bounds.width &&
                    y >= bounds.y && y <= bounds.y + bounds.height) {
                    return nodeArea;
                }
            }
            return null;
        }
        
        // 处理节点点击
        function handleNodeClick(event, nodeArea, container) {
            console.log('点击了节点:', nodeArea.nodeName, nodeArea.config);
            
            // 添加点击动画效果
            addClickEffect(event, container);
            
            // 高亮节点
            highlightNode(nodeArea);
            currentSelectedNode = nodeArea.nodeId;
            
            // 显示信息面板
            showNodeInfoPanel(event, nodeArea);
        }
        
        // 添加点击动画效果
        function addClickEffect(event, container) {
            const ripple = document.createElement('div');
            ripple.className = 'click-indicator';
            
            const containerRect = container.getBoundingClientRect();
            ripple.style.left = (event.clientX - containerRect.left - 15) + 'px';
            ripple.style.top = (event.clientY - containerRect.top - 15) + 'px';
            
            container.appendChild(ripple);
            
            setTimeout(() => {
                if (ripple.parentNode) {
                    ripple.parentNode.removeChild(ripple);
                }
            }, 800);
        }
        
        // 高亮节点
        function highlightNode(nodeArea) {
            // 重置所有节点样式
            nodeAreas.forEach(area => {
                area.element.classList.remove('node-highlighted');
            });
            
            // 高亮当前节点
            nodeArea.element.classList.add('node-highlighted');
        }
        
        // 显示节点信息面板
        function showNodeInfoPanel(event, nodeArea) {
            const panel = document.getElementById('node-info-panel');
            const title = document.getElementById('panel-title');
            const status = document.getElementById('panel-status');
            const metrics = document.getElementById('panel-metrics');
            const actionList = document.getElementById('action-list');
            
            title.textContent = nodeArea.config.name;
            
            // 设置状态样式
            status.textContent = getStatusText(nodeArea.config.status);
            status.className = `panel-status badge-${nodeArea.config.status}`;
            
            // 显示节点指标
            metrics.innerHTML = '';
            Object.entries(nodeArea.config.metrics).forEach(([key, value]) => {
                const metricDiv = document.createElement('div');
                metricDiv.className = 'metric-item';
                metricDiv.innerHTML = `
                    <span class="metric-value">${value}</span>
                    <div class="metric-label">${key}</div>
                `;
                metrics.appendChild(metricDiv);
            });
            
            // 清空并重新填充操作列表
            actionList.innerHTML = '';
            
            nodeArea.config.actions.forEach(action => {
                const button = document.createElement('button');
                button.className = 'action-button';
                button.innerHTML = `
                    <div class="action-info">
                        <span style="font-size: 16px; margin-right: 8px;">${action.icon}</span>
                        <span>${action.name}</span>
                    </div>
                    <div class="action-timeout">${action.timeout}s</div>
                `;
                button.onclick = () => executeAction(nodeArea.nodeId, action);
                actionList.appendChild(button);
            });
            
            // 定位面板
            const x = Math.min(event.pageX + 20, window.innerWidth - 480);
            const y = Math.min(event.pageY + 20, window.innerHeight - 500);
            
            panel.style.left = x + 'px';
            panel.style.top = y + 'px';
            panel.style.display = 'block';
        }
        
        // 执行节点操作
        async function executeAction(nodeId, action) {
            console.log(`执行操作: ${nodeId} -> ${action.name}`);
            
            showLoading(true, `正在执行 ${action.name}...`);
            hideInfoPanel();
            
            try {
                const response = await fetch('/api/scripts/execute', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        nodeId: nodeId,
                        capabilityId: action.id
                    })
                });
                
                const data = await response.json();
                
                if (response.ok && data.status === 'success') {
                    lastExecutionResult = data;
                    showNotification(`✅ ${action.name} 执行成功`, 'success');
                    
                    // 显示详细结果
                    setTimeout(() => {
                        showExecutionModal(data, action);
                    }, 1000);
                } else {
                    throw new Error(data.error || '执行失败');
                }
                
            } catch (error) {
                console.error('执行失败:', error);
                showNotification(`❌ ${action.name} 执行失败: ${error.message}`, 'error');
            } finally {
                showLoading(false);
            }
        }
        
        // 显示执行结果模态框
        function showExecutionModal(data, action) {
            const modal = document.getElementById('execution-modal');
            const title = document.getElementById('modal-title');
            const info = document.getElementById('execution-info');
            const output = document.getElementById('execution-output');
            
            title.textContent = `${action.icon} ${action.name} - 执行结果`;
            
            info.innerHTML = `
                <div>
                    <strong>节点:</strong> ${data.nodeId} | 
                    <strong>执行ID:</strong> ${data.executionId}
                </div>
                <div>
                    <strong>耗时:</strong> ${data.duration}ms | 
                    <strong>状态:</strong> <span style="color: #27ae60; font-weight: bold;">${data.status}</span> |
                    <strong>时间:</strong> ${new Date(data.timestamp).toLocaleString()}
                </div>
            `;
            
            output.textContent = data.output;
            
            modal.style.display = 'flex';
        }
        
        // 工具函数
        function getStatusText(status) {
            const statusMap = {
                'healthy': '运行正常',
                'warning': '需要关注',
                'critical': '严重问题',
                'maintenance': '维护中'
            };
            return statusMap[status] || '状态未知';
        }
        
        function showLoading(show, message = '加载中...') {
            const overlay = document.getElementById('loading-overlay');
            const text = overlay.querySelector('.loading-text');
            
            if (text) {
                text.textContent = message;
            }
            
            overlay.style.display = show ? 'flex' : 'none';
        }
        
        function showNotification(message, type = 'success') {
            const notification = document.createElement('div');
            notification.style.cssText = `
                position: fixed;
                top: 30px;
                right: 30px;
                background: ${type === 'error' ? 'linear-gradient(135deg, #e74c3c, #c0392b)' : 
                           type === 'warning' ? 'linear-gradient(135deg, #f39c12, #e67e22)' : 
                           'linear-gradient(135deg, #27ae60, #2ecc71)'};
                color: white;
                padding: 15px 20px;
                border-radius: 10px;
                box-shadow: 0 6px 20px rgba(0,0,0,0.2);
                z-index: 4000;
                font-weight: 500;
                max-width: 300px;
                animation: slideInRight 0.3s ease-out;
            `;
            notification.textContent = message;
            
            document.body.appendChild(notification);
            
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.style.animation = 'slideOutRight 0.3s ease-in';
                    setTimeout(() => {
                        if (notification.parentNode) {
                            notification.parentNode.removeChild(notification);
                        }
                    }, 300);
                }
            }, 4000);
        }
        
        function updateDiagramInfo() {
            const info = document.getElementById('diagram-info');
            info.textContent = `PlantUML v8059 | ${nodeAreas.length} 个节点 | ${new Date().toLocaleTimeString()}`;
        }
        
        // 面板控制函数
        function hideInfoPanel() {
            document.getElementById('node-info-panel').style.display = 'none';
            currentSelectedNode = null;
            
            // 清除节点高亮
            nodeAreas.forEach(area => {
                area.element.classList.remove('node-highlighted');
            });
        }
        
        function hideExecutionModal(event) {
            if (!event || event.target === document.getElementById('execution-modal')) {
                document.getElementById('execution-modal').style.display = 'none';
            }
        }
        
        function refreshNodeMetrics() {
            if (currentSelectedNode) {
                showNotification('🔄 正在刷新节点指标...', 'success');
                // 这里可以调用API刷新实时数据
            }
        }
        
        function copyOutput() {
            if (lastExecutionResult && lastExecutionResult.output) {
                navigator.clipboard.writeText(lastExecutionResult.output).then(() => {
                    showNotification('📋 输出已复制到剪贴板', 'success');
                }).catch(() => {
                    showNotification('❌ 复制失败', 'error');
                });
            }
        }
        
        // 控制面板功能
        function reloadDiagram() {
            showNotification('🔄 正在重新加载架构图...', 'success');
            hideInfoPanel();
            initializePlantUMLDiagram();
        }
        
        function analyzeDiagram() {
            showNotification(`🔍 架构分析完成: ${nodeAreas.length} 个节点，${nodeAreas.filter(n => n.config.status !== 'healthy').length} 个需要关注`, 'success');
        }
        
        function exportSVG() {
            const svgElement = document.querySelector('#plantuml-container svg');
            if (svgElement) {
                try {
                    const svgData = new XMLSerializer().serializeToString(svgElement);
                    const svgBlob = new Blob([svgData], {type: 'image/svg+xml;charset=utf-8'});
                    const svgUrl = URL.createObjectURL(svgBlob);
                    
                    const downloadLink = document.createElement('a');
                    downloadLink.href = svgUrl;
                    downloadLink.download = `architecture-${new Date().toISOString().slice(0,10)}.svg`;
                    document.body.appendChild(downloadLink);
                    downloadLink.click();
                    document.body.removeChild(downloadLink);
                    
                    URL.revokeObjectURL(svgUrl);
                    showNotification('📥 架构图已导出', 'success');
                } catch (error) {
                    showNotification('❌ 导出失败: ' + error.message, 'error');
                }
            }
        }
        
        function toggleDevMode() {
            devMode = !devMode;
            showNotification(`⚙️ 开发模式已${devMode ? '开启' : '关闭'}`, 'success');
            
            // 重新分析结构以应用/移除调试叠加层
            const svgElement = document.querySelector('#plantuml-container svg');
            const container = document.getElementById('plantuml-container');
            if (svgElement) {
                analyzeSVGStructure(svgElement, container);
            }
        }
        
        // 键盘快捷键
        document.addEventListener('keydown', (event) => {
            if (event.key === 'Escape') {
                hideInfoPanel();
                hideExecutionModal();
            } else if (event.key === 'F5' || (event.ctrlKey && event.key === 'r')) {
                event.preventDefault();
                reloadDiagram();
            } else if (event.ctrlKey && event.key === 'd') {
                event.preventDefault();
                toggleDevMode();
            }
        });
        
        // 添加CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideInRight {
                from { transform: translateX(100%); opacity: 0; }
                to { transform: translateX(0); opacity: 1; }
            }
            @keyframes slideOutRight {
                from { transform: translateX(0); opacity: 1; }
                to { transform: translateX(100%); opacity: 0; }
            }
        `;
        document.head.appendChild(style);
        
        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initializePlantUMLDiagram();
            console.log('PlantUML 交互演示已初始化');
        });
    </script>
</body>
</html>